package com.ch13.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @ClassName UserServiceAspect
 * @Description
 * @Author Kx
 * @Date 2025/5/6 10:59
 * @Version 1.0
 */
// 表示当前类是一个切面类
@Aspect
// 把当前Bean交给容器管理
@Component
public class UserServiceAspect {

    /**
     * @author: kx
     * @date: 2025/5/6 11:28
     * @description: 使用@Pointcut注解标识在一个任意的方法上表示未切入点(即表示把通知插入到哪里去)
     * 主要是编写切入点表达式(AspectJ的切入点表达式)
     * execution()是用来执行切入点表达式的一个函数
     * 下面的表达式中:
     * 第一个星号: 表示连接点方法的访问修饰符
     * 第二个星号: 表示所有类
     * 第三个星号: 表示类下面的所有方法
     * (星号可以改为具体的类名或者方法名)
     * (..) 表示任意类型和个数的参数
     * 因此,被切入点表达式找到的这些方法都称之为连接点
    */
    @Pointcut("execution(* com.ch13.service.UserService.*(..))")
    public void pointCut(){
    }

    /**
     * @author: kx
     * @date: 2025/5/6 11:34
     * @param joinPoint : 表示连接点信息(目标方法的信息)
     * @description: 前置通知
    */
    // 表示在pointCut()方法中定义的连接点之前执行before()方法
    @Before("pointCut()")
    public void before(JoinPoint joinPoint) {
        // 输出拦截方法的第一个参数
        System.out.println("前置通知," + "参数:" + joinPoint.getArgs()[0]);
    }

    /**
     * @author: kx
     * @date: 2025/5/6 11:38
     * @param joinPoint : 表示连接点信息(目标方法的信息)
     * @param result : 表示目标方法的返回值
     * @description: 后置通知
    */
    @AfterReturning(value = "pointCut()",returning = "result")
    public Object after(JoinPoint joinPoint,String result) {
        System.out.println("后置通知," + "结果:" + result);
        return result;
    }

    /**
     * @author: kx
     * @date: 2025/5/6 11:48
     * @param proceedingJoinPoint : 表示连接点信息(目标方法的信息)
     * @description: 环绕通知
    */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable {
        System.out.println("环绕通知前");

        // 调用方法
        Object proceed = proceedingJoinPoint.proceed();

        System.out.println("环绕通知后");

        return proceed;
    }

    /**
     * @author: kx
     * @date: 2025/5/6 11:54
     * @param joinPoint : 表示连接点信息(目标方法的信息)
     * @param e : 表示异常信息
     * @description: 异常通知
    */
    @AfterThrowing(value = "pointCut()",throwing = "e")
    public void afterThrowing(JoinPoint joinPoint,Throwable e) {
        System.out.println("异常通知" + e.getMessage());
    }

    /**
     * @author: kx
     * @date: 2025/5/6 11:56
     * @param joinPoint : 表示连接点信息(目标方法的信息)
     * @description: 最终通知
    */
    @After("pointCut()")
    public void afterFinally(JoinPoint joinPoint) {
        System.out.println("最终通知");
    }
}
